﻿//===============================================================================
// TRONSoft
//
// Shifter
//
//===============================================================================
// Copyright © Ton de Ron.
//
// All rights reserved.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//
//===============================================================================

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

using Shifter.Utils;

namespace Shifter.Selectors
{
    public class ConstructorSelector : UnarySelectorBase<ConstructorInfo>
    {
        public override ConstructorInfo Selecter(IShifterContext context)
        {
            Assume.ArgumentNotNull(context, "context");

            var constructors = new List<ConstructorInfo>
            (
                context.TypeToResolve
                    .GetTypeInfo()
                    .DeclaredConstructors
                    .Where(c => c.IsFamily || c.IsPublic || c.IsPrivate == context.Container.Options.ResolvePrivateMembers)
            );
            var injectMarkedConstructors = constructors.FindAll(constructor => constructor.IsDefined(typeof(InjectAttribute), false));

            if (injectMarkedConstructors.Count > 1)
            {
                throw new NotSupportedException(Strings.MultipleConstructorInjectionIsNotSupported);
            }
            else if (injectMarkedConstructors.Count == 1)
            {
                return injectMarkedConstructors[0];
            }
            else if (constructors.Count > 0)
            {
                return constructors[0];
            }
            else
            {
                return context.TypeToResolve.GetTypeInfo()
                    .DeclaredConstructors
                    .FirstOrDefault(c => !c.GetParameters().Any());
            }
        }
    }
}